Examination of SID triangle waveform

Data recorded on the triangle waveform ($10)

The data are recorded using a REU. The recording is done like this:
        ;* Program 1 *

	;Turn off screen and sprites

	...

	;Set frequency of voice 3

	LDA #<freq
	LDX #>freq
	STA $D40E
	STX $D40F

	;Reset waveform

	LDA #$08	;Set test bit
	STA $D412

	;Setup REU to sample register $D41B for $10000 cycles

	...

	;Start recording

	LDA #$10	;Waveform: Triangle
	LDX #%1001000	;REU-command: Start transfer
	STA $D412	;Start waveform
	STX $DF01	;Start transfer

	...
Furthermore, a construct like this is used to get a value from the waveform as fast as possible (via software) from the SID:
	;* Program 2 *

	...

	LDA #$10
	STA $D412	;Start waveform
	LDA $D41B	;Record early value
	STA Haps	;Save value

	...
The table below summarizes the recordings (all values in hex):
Frequency  Haps REU

8000	   04   05 06 07 ... FD FE FF FF FE ... 01 00 00 01 ...
4000       02   02 03 03 04 04 ...
2000       01   01 01 01 02 02 02 02 03 03 03 03 04 ...
1000       00   00 00 00 01 01 01 01 01 01 01 01 01 02 ...
FFFF       07   09 0B 0D 0F 11 13 15 17
DEAD       06   08 0A 0C 0D 0F 11 13 14 16 18 1A 1B 1D 1F 21 22 24 26
                28 29 2B 2D 2E 30 32 34 35 37 39 3B 3C 3E 40 42 43 45
                47 49 4A 4C 4E 50 51 53 55 56 58 5A 5C 5D 5F 61 63 64
Legend:
Frequency is the value stored to $D40E and $D40F.
Haps is the value of the Haps variable from program 2.
REU is the data collected with the REU after running program 1.

Conclusion: The triangle waveform starts with value $00 and goes to $ff linearly. Then it goes from $ff to $00 linearly.
(As a sidenote, I'll mention that the data for the sawtooth waveform at frequency $8000 is Haps= 02, REU= 02 03 03 04 04 ... FE FE FF FF 00 00 01 01 ...)
The Haps variable is the value of the waveform on one cycle earlier than the REU starts recording.

Further data used to investigate the frequency/waveform mapping:
Frequency
      Haps+REU, Number of this*value

0001  7FFC*00 8000*01 8000*02 ...
0002  3FFC*00 4000*01 4000*02 ...
0003  2AA7*00 2AAB*01 2AAA*02 2AAB*03
0004  1FFC*00 2000*01 2000*02 ...
0005  1996*00 199A*01 1999*02 199A*03 1999*04
0006  1552*00 1555*01 1555*02 1556*03 1555*04 1555*05 1556*06
0007  1245*00 1249*01 1249*02 1249*03 1249*04 1249*05 1249*06 124A*07
      1249*08
0008  0FFC*00 1000*01 1000*02 ...
0009  0E35*00 0E39*01 0E39*02
000A  0CC9*00 0CCD*01
000B  0B9F*00
Legend:
Frequency is the value stored to $D40E and $D40F.
Haps+REU is the contents of the Haps variable from program 2 and the contents of the REU after running program 1.
The format is number of times of repeation * value. (i.e. 7FFC*00 means that the value "00" repeated $7FFC times after each other in the data. 0003*FE 0004*DE would mean this sequence of data was recorded: FE FE FE DE DE DE DE. The first FE would come from the variable Haps, while the rest would be obtained with the REU.)

Conclusion: We know that with the STA $D412; LDA $D41B construct, A contains the value of the waveform after 4 cycles. This is consistence with the observation that the number of times the value $00 appears generally is 4 lower than the number of times the other values appear.

The overall behaviour can thus be simulated with this C-program:
void Triangle(long Frequency) {
  long Cycle; /* Count of Phi2 cycles */

  long Delay= 0x8000;
  long Counter= 0; /* Initial value is 0 */

  for (Cycle=0; ;Cycle= Cycle+1) {

    /* Build waveform: Triangle */
    if (Counter  256)
      Waveform[cycle]= Counter;
    else
      Waveform[cycle]= 511- Counter;

    /*
      For the sawtooth waveform, use:

      Waveform[Cycle]= Counter / 2;
    */

    /* Handle frequency-function */
    Delay = Delay- Frequency;

    /* Frequency overflow? */
    while (Delay =0 ) do {
    >

Übertragung unterbrochen!